package com.starlink.utils.impl;

import com.starlink.utils.IRedisCacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author zhouyuhang
 * @date 2022/7/20 11:09
 */
@Slf4j
@Component
public class RedisCacheServiceImpl implements IRedisCacheService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();
    private static final GenericJackson2JsonRedisSerializer VALUE_SERIALIZER = new GenericJackson2JsonRedisSerializer();
    private static final long LOCK_EXPIRE_SECONDS = 10;

    @PostConstruct
    public void valid() {
        redisTemplate.setKeySerializer(STRING_SERIALIZER);
        redisTemplate.setValueSerializer(STRING_SERIALIZER);

        redisTemplate.setHashKeySerializer(VALUE_SERIALIZER);
        redisTemplate.setHashValueSerializer(VALUE_SERIALIZER);

        log.warn("======>初始化Redis服务成功 {}", this.getClass().getCanonicalName());
    }

    @Override
    public boolean tryLock(String lockKey) {
        Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked");
        if (lockAcquired != null && lockAcquired) {
            redisTemplate.expire(lockKey, LOCK_EXPIRE_SECONDS, TimeUnit.SECONDS);
            return true;
        }
        return false;
    }

    @Override
    public void releaseLock(String lockKey) {
        redisTemplate.delete(lockKey);
    }

    @Override
    public void deleteFromRedis(String key) {
        redisTemplate.delete(key);
    }

    @Override
    public Boolean hashCheckExists(String mapName, String field) {
        return redisTemplate.opsForHash().hasKey(mapName, field);
    }

    @Override
    public <T> T hashGet(String tableName, String hashKey) {
        return (T) redisTemplate.opsForHash().get(tableName, hashKey);
    }

    @Override
    public Map<Object, Object> hashGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    @Override
    public Long hashIncrementLongOfHashMap(String hKey, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(hKey, hashKey, delta);
    }

    @Override
    public Double hashIncrementDoubleOfHashMap(String hKey, String hashKey, Double delta) {
        return redisTemplate.opsForHash().increment(hKey, hashKey, delta);
    }

    @Override
    public <T> void hashPushHashMap(String key, String hashKey, T value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    @Override
    public void hashPushHashMap(String key, String hashKey, Object value, long timeout, TimeUnit timeUnit) {
        redisTemplate.opsForHash().put(key, hashKey, value);
        redisTemplate.expire(key, timeout, timeUnit);
    }

    @Override
    public Set<Object> hashGetAllHashKey(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    @Override
    public Long hashGetHashMapSize(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    @Override
    public List<Object> hashGetHashAllValues(String key) {
        return redisTemplate.opsForHash().values(key);
    }

    @Override
    public Long hashDeleteHashKey(String key, Object... hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    @Override
    public void listLeftPushList(String key, String value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    @Override
    public Object listLeftPopList(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    @Override
    public Long listSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    @Override
    public List<String> listRangeList(String key, Long start, Long end) {
        return (List<String>) (List) redisTemplate.opsForList().range(key, start, end);
    }

    @Override
    public Long listRemoveFromList(String key, long i, Object value) {
        return redisTemplate.opsForList().remove(key, i, value);
    }

    @Override
    public String listIndexFromList(String key, long index) {
        return (String) redisTemplate.opsForList().index(key, index);
    }

    @Override
    public void listSetValueToList(String key, long index, String value) {
        redisTemplate.opsForList().set(key, index, value);
    }

    @Override
    public void listTrimByRange(String key, Long start, Long end) {
        redisTemplate.opsForList().trim(key, start, end);
    }

    @Override
    public void listRightPushList(String key, String value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    @Override
    public String listRightPopList(String key) {
        return (String) redisTemplate.opsForList().rightPop(key);
    }

    @Override
    public Long setAddSetMap(String key, String... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    @Override
    public Long setGetSizeForSetMap(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    @Override
    public Long deleteValueInSetMap(String key, String value) {
        return redisTemplate.opsForSet().remove(key, value);
    }

    @Override
    public Set<String> setGetMemberOfSetMap(String key) {
        return (Set<String>) (Set) redisTemplate.opsForSet().members(key);
    }

    @Override
    public Boolean setCheckIsMemberOfSet(String key, Object o) {
        return redisTemplate.opsForSet().isMember(key, o);
    }

    @Override
    public Integer stringAppendString(String key, String value) {
        return redisTemplate.opsForValue().append(key, value);
    }

    @Override
    public String stringGetStringByKey(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    @Override
    public String stringGetSubStringFromString(String key, long start, long end) {
        return redisTemplate.opsForValue().get(key, start, end);
    }

    @Override
    public Long stringIncrementLongString(String key, Long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    @Override
    public Double stringIncrementDoubleString(String key, Double delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    @Override
    public void stringSetString(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public String stringGetAndSet(String key, String value) {
        return (String) redisTemplate.opsForValue().getAndSet(key, value);
    }

    @Override
    public void stringSetValueAndExpireTime(String key, String value, long timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.MILLISECONDS);
    }

    @Override
    public Long getExpireTime(String key, TimeUnit timeUnit) {
        return redisTemplate.getExpire(key, timeUnit);
    }

    @Override
    public boolean setIfAbsent(String key, Object value) {
        if (null == value) {
            return false;
        }
        return redisTemplate.boundValueOps(key).setIfAbsent(String.valueOf(value));
    }
}
